# -*- coding: utf8 -*-

__author__ = 'sergey'

import traceback
from time import sleep, time
import gobject
from datetime import datetime, timedelta
from threading import Thread, Event

class FindDupArchives(Thread):
    """
    __init__ : args = ( app, ui, db_req, stats_req )
    """

    app = None
    ui = None
    db_req = None
    stats_req = None

    stop_event = None
    done = False

    log = None

    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, verbose=None):
        self.app, self.ui, self.db_req, self.stats_req = args
        self.stop_event = Event()
        Thread.__init__(self, group, target, name, args, kwargs, verbose)

    def run(self):
        from logger import get_file_logger
        self.log = get_file_logger("worker-FindDupArchives")
        try:
            self.stop_event.clear()
            self.find_duparchives()
        except Exception as e:
            self.log.error(e)
            self.log.error(traceback.format_exc())
        self.db_req.close()
        return 0


    def match_func(self, model, iter, data):
        column, key = data # data is a tuple containing column number, key
        value = model.get_value(iter, column)
        return value == key

    def search(self, model, iter, func, data):
        while iter:
            if func(model, iter, data):
                return iter
            result = self.search(model, model.iter_children(iter), func, data)
            if result: return result
            iter = model.iter_next(iter)
        return None


    def add_file_to_treeview(self, file1, file2, file2file, store):

        if not file2file["equal_images"]:
            return
        elif not file2file["file2_count"] or not file2file["file1_count"]:
            return
        elif file2file["file2_count"] and file2file["file1_count"]:
            eq1 = file2file["equal_images"] * 100 / file2file["file1_count"]
            eq2 = file2file["equal_images"] * 100 / file2file["file2_count"]

            if file2file["file2_count"] > file2file["file1_count"]:
                # Almost all files in 1st archive must be equal to 2nd atchive images
                if abs(100 - eq1) > 5:
                    return
            else:
                # Almost all files in 2nd archive must be equal to 1st atchive images
                if abs(100 - eq2) > 5:
                    return

        self.similar += 1

        file1_id_str = str(file2file["file1_id"])
        file2_id_str = str(file2file["file2_id"])

        file1_iter = store.append( None, [
            file1_id_str,
            None,
            self.app.idle_button_view_dup_file_clicked,
            self.app.idle_button_del_dup_file_clicked,
            self.db_req.get_file_full_path( file1 ),
            file2file["file1_count"],
            None,
            None,
            "Посмотреть",
            "Удалить"
        ])

        store.append( file1_iter, [
            None,
            file2_id_str,
            self.app.idle_button_view_dup_file_clicked,
            self.app.idle_button_del_dup_file_clicked,
            self.db_req.get_file_full_path( file2 ),
            file2file["file2_count"],
            file2file["equal_images"],
            file2file["quality_points"],
            "Посмотреть",
            "Удалить",
        ])

        return


    def update_ui( self ):

        if self.f2f_count:
            p = self.processed * 1.0 / self.f2f_count
            s = self.similar * 1.0 / self.f2f_count
        else:
            p = 0
            s = 0
        if p < 0:
            p = 0
        if p > 1:
            p = 1
        if s < 0:
            s = 0
        if s > 1:
            s = 1

        t_now = time()

        if self.processed:
            eta = timedelta( seconds=(t_now - self.t_begin) * (self.f2f_count * 1.0 / self.processed - 1) )
        else:
            eta = timedelta( seconds=0 )

        gobject.idle_add( self.ui.get_object("progressbar_nonuniq_archives").set_fraction, p )

        title = self.ui.get_object("window1").get_title()
        new_title = "[ %.2f %% ], %s" % ( p * 100, self.app.get_ui_title(), )
        if title != new_title:
            gobject.idle_add( self.ui.get_object("window1").set_title, new_title )

        if self.processed < self.f2f_count and not self.done:
            gobject.idle_add( self.ui.get_object("progressbar_nonuniq_archives").set_text,
                "Обработано: %d из %d (%0.3f%%), Найдено: %d (%0.3f%%), Завершение через: %s" % (
                    self.processed, self.f2f_count, p * 100, self.similar, s * 100.0, eta
                )
            )
            return True
        else:
            dt = timedelta( seconds=(t_now - self.t_begin))
            gobject.idle_add( self.ui.get_object("progressbar_nonuniq_archives").set_text,
                "Обработано: %d из %d (%0.3f%%), Найдено: %d (%0.3f%%), Заняло: %s" % (
                    self.processed, self.f2f_count, p * 100, self.similar, s * 100.0, dt
                )
            )
        return False


    def find_duparchives(self):

        self.log.info("START")

        treeview4 = self.ui.get_object("treeview4")
        store_file = treeview4.get_model()

        store_file.clear()

        self.log.debug("Get file2file count...")
        t1 = datetime.now()
        self.f2f_count = self.db_req.get_file2file_count()
        t2 = datetime.now()
        self.log.debug("Got file2file count: %s, in %s" % (self.f2f_count, t2 - t1))

        self.processed = 0
        self.similar = 0

        gobject.idle_add( self.ui.get_object("progressbar_nonuniq_archives").set_text,
            "Обработано: %d из %d (%0.3f%%); Найдено: %d (%0.3f%%)" % (
                self.processed, self.f2f_count, 0,
                self.similar, 0
            )
        )

        self.done = False

        if not self.f2f_count:
            self.done = True
            self.log.info("STOP")
            return 0

        offset = 0
        count = 1000

        self.log.debug(".. offset=%d, count=%d, processed=%d" % (offset, count, self.processed))

        t1 = datetime.now()
        items = list(self.db_req.get_file2file(count, offset))
        t2 = datetime.now()
        self.log.debug("Got file2file in %s" % (t2 - t1,))

        self.t_begin = time()

        gobject.timeout_add( 200, self.update_ui )

        while not self.stop_event.isSet():
            try:
                item = items.pop()
            except:
                item = None

            # self.log.debug("Item=%r" % item)
            # print("-- item: %r" % (item,))
            if item is None:
                if offset + count >= self.f2f_count:
                    self.stop_event.set()
                    break
                offset += count
                self.log.debug(".. offset=%d, count=%d, processed=%d" % (offset, count, self.processed))
                t1 = datetime.now()
                items = list(self.db_req.get_file2file(count, offset))
                t2 = datetime.now()
                self.log.debug("Got file2file in %s" % (t2 - t1,))
                continue


            file1 = self.db_req.get_file(item["file1_id"])
            file2 = self.db_req.get_file(item["file2_id"])

            self.add_file_to_treeview( file1, file2, item, store_file)

            self.processed += 1

        self.log.debug(".. offset=%d, count=%d, processed=%d" % (offset, count, self.processed))

        self.done = True
        self.log.info("STOP")

        if not self.stop_event.isSet():
            self.ui.get_object("button_find_duparchives").set_active(False)

        return
